﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.TagHelpers.Cache;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using 旅游管理系统.Dtos;

namespace 旅游管理系统.Controllers
{
    [ApiController]
    [Route("auth")]
    public class AuthenticateController : ControllerBase
    {
        private readonly IConfiguration _configuration;

        public AuthenticateController(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        [AllowAnonymous] //因为这个 api是每个人都可以访问的，需要加这个[AllowAnonymous]，但是这个是可加可不加，加上代码更清晰一点
        [HttpPost("login")] //登录 api应该是一个 Post请求
        public IActionResult login([FromRoute] LoginDto loginDto)
        {
            //至于 login函数的参数应该是 post请求主体的 json数据登录名和密码，应该专门创建一个 loginDto来处理 JSON数据的反序列化。
            //第一步 验证用户名和密码

            //第二部 如果用户名和密码正确，则创建 jwt 。在创建 jwt之前应先安装关于 jwt的框架 jwtbearer
            //header    定义了Token编码的算法
            var signingAlgorithm = SecurityAlgorithms.HmacSha256;
            //payload    属于自定义内容，需要根据项目的需求进行填写，可能会用到用户的ID或用户名或者是Email，对于这些数据需要使用 Claim来进行处理 。Claim暂时理解为jwt中自定义 payload数据，是一个数组
            var claims = new[]
            {
                // sub
                new Claim(JwtRegisteredClaimNames.Sub,"fake_user_id")
            };

            //signiture   数字签名需要使用到私钥，可以把私钥放在项目的配置文件 appsettings.json中
            var secreByte = Encoding.UTF8.GetBytes(_configuration["Authentication : SecretKey"]);
            var signingKey = new SymmetricSecurityKey(secreByte); //使用非对称加密算法对私钥进行加密
            var signingCredentials = new SigningCredentials(signingKey, signingAlgorithm);//使用 HmacSha256来验证对非对称加密的私钥
            var token = new JwtSecurityToken(
                issuer : _configuration["Authentication"],
                audience : _configuration["Authentication : Audience"],
                claims,
                notBefore : DateTime.UtcNow,
                expires : DateTime.UtcNow.AddDays(1),
                signingCredentials
            );
            var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);

            //第三步 jwt成功创建以后在响应主体中应该添加 jwt的数据 200 OK (return 200 ok + jwt)
            return Ok(tokenStr);
        }
    }
}
